﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using ITAP.Core.Modelling.Primitives;
using ITAP.ContourBuilder.Constraints;

using ITAP.Core.Calculations;
using ITAP.Core.Modelling;

namespace ITAP.ContourBuilder.Components
{
    [Serializable]
    public abstract class ContourComponent : IContourComponent
    {
        private bool modified = false;
        public bool Modified
        {
            get { return modified; }
            set { modified = value; }
        }

        protected bool isPrimitiveDependsOnDisplayParameters = true;

        public virtual bool IsPrimitiveDependsOnDisplayParameters
        {
            get { return isPrimitiveDependsOnDisplayParameters; }
        }

        private string name;

        public string Name
        {
            get { return name; }
            set { name = value; }
        }

        public ContourComponent()
        {
            this.acceptedTypesToConnect = new List<Type>();
            this.componentsInTolerance = new List<IContourComponent>();
            this.connectedComponents = new List<IContourComponent>();
            this.constraints = new List<IContourConstraint>();
            this.innerComponents = new List<IContourComponent>();

        }

        protected List<IContourComponent> connectedComponents;
        public IEnumerable<IContourComponent> ConnectedComponents
        {
            get { return connectedComponents; }
        }

        protected List<IContourComponent> innerComponents;
        public IEnumerable<IContourComponent> InnerComponents
        {
            get { return innerComponents; }
        }

        protected List<IContourConstraint> constraints;
        public IEnumerable<IContourConstraint> Constraints
        {
            get { return constraints; }
        }

        protected List<IContourComponent> componentsInTolerance;
        public ICollection<IContourComponent> ComponentsInTolerance
        {
            get { return componentsInTolerance; }
        }

        protected List<Type> acceptedTypesToConnect;
        public ICollection<Type> AcceptedTypesToConnect
        {
            get { return acceptedTypesToConnect; }
        }

        private IPrimitive primitive;
        public virtual IPrimitive Primitive
        {
            get
            {
                return primitive;
            }
            set
            {
                primitive = value;
            }
        }

        public virtual RectangleF BoundingBox
        {
            get
            {
                throw new NotImplementedException();
            }
        }

        public virtual void Update()
        {
            foreach (IContourConstraint constraint in this.constraints)
            {
                if (!this.enableConstraints)
                    break;

                if (!constraint.Enabled)
                    continue;

                if (!constraint.Check(this))
                    constraint.Fix(this);
            }
        }

        private IContourComponent parent;
        public virtual IContourComponent Parent
        {
            get
            {
                return parent;
            }
            set
            {
                parent = value;
            }
        }

        private int serialNumber;
        public int SerialNumber
        {
            get
            {
                return serialNumber;
            }
            set
            {
                serialNumber = value;
            }
        }

        private bool enableConstraints = true;
        public bool EnableConstraints
        {
            get
            {
                return enableConstraints;
            }
            set
            {
                enableConstraints = value;
            }
        }

        protected bool selected;
        public virtual bool Selected
        {
            get
            {
                return selected;
            }
            set
            {
                selected = value;
            }
        }


        #region IContourComponent Members


        public virtual IContourComponent ConnectTo(IContourComponent component)
        {
            if (this.connectedComponents.Contains(component))
                return null;

            this.connectedComponents.Add(component);
            return this;
        }

        public virtual IContourComponent ConnectToEnded(IEndedContourComponent component, EndType endToConnect)
        {
            throw new NotImplementedException();
        }

        public virtual IContourComponent DisconnectFrom(IContourComponent component)
        {
            if (this.connectedComponents.Contains(component))
            {
                this.connectedComponents.Remove(component);
                return this;
            }
            else
                return null;
        }

        public virtual ModelPoint Position
        {
            get { throw new NotImplementedException(); }
        }

        public virtual void MoveTo(ModelPoint destination)
        {
            ModelPoint currentPosition = this.Position;
            ModelVector offset = new ModelVector(currentPosition, destination);
            this.Primitive.MoveWithOffset(offset);
        }

        public virtual void MoveWithOffset(ModelVector offset)
        {
            this.Primitive.MoveWithOffset(offset);
        }

        public virtual void SelectByPoint(ModelPoint point)
        {
            RectangleF bbox = this.BoundingBox;
            PointF floatPoint = new PointF((float)point.X, (float)point.Y);
            if (bbox.Contains(floatPoint))
                this.selected = true;
        }

        public virtual bool CanSelectByPoint(ModelPoint point)
        {
            throw new NotImplementedException();
        }

        public virtual double Tolerance
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        protected int screenWidth;
        protected int screenHeight;
        protected RectangleF modelRectangle;
        [NonSerialized]
        protected ModelCoordinateConverter coordinateConverter;
        [NonSerialized]
        protected ModelPoint cameraCenter;

        public void SetDisplayParameters(int screenWidth, int screenHeight, RectangleF modelRectangle, ModelCoordinateConverter coordinateConverter, ModelPoint cameraCenter)
        {
            this.screenWidth = screenWidth;
            this.screenHeight = screenHeight;
            this.modelRectangle = modelRectangle;
            this.coordinateConverter = coordinateConverter;
            this.cameraCenter = cameraCenter.Clone() as ModelPoint;
        }

        public virtual void AcceptVisitor(IContourVisitor visitor)
        {
            throw new NotImplementedException();
        }

        public virtual bool IsInTolerance(ModelPoint point, double tolerance)
        {
            return this.CanSelectByPoint(point);
        }

        public virtual bool IsComponentDotted
        {
            get { throw new NotImplementedException(); }
        }

        #endregion

        #region IContourVisitor Members

        public virtual void Visit(ContourModel model)
        {
        }

        public virtual void Visit(ContourContainer container)
        {
        }

        public virtual void Visit(ContourElement element)
        {
        }

        public virtual void Visit(ContourConnector connector)
        {
        }

        public virtual void Visit(ContourElementHook hook)
        {
        }

        #endregion

        #region ICloneable Members

        public virtual object Clone()
        {
            throw new NotImplementedException();
        }

        #endregion

        #region IContourVisitor Members


        public virtual void Visit(ContourText text)
        {
            //throw new NotImplementedException();
        }

        #endregion

        #region IContourVisitor Members


        public virtual void Visit(ContourCommentLine commentLine)
        {
        }

        #endregion

        #region IContourVisitor Members


        public virtual void Visit(ITAP.ContourBuilder.Components.Dimensions.Dimension dimension)
        {
            //throw new NotImplementedException();
        }

        #endregion

        #region IContourVisitor Members


        public void Visit(ContourHole hole)
        {
           // throw new NotImplementedException();
        }

        #endregion

        #region IContourComponent Members

        private int id;
        public virtual int Id
        {
            get
            {
                return id;
            }
            set
            {
                id = value;
            }
        }

        #endregion

        #region IContourComponent Members

        protected bool hasBoundingBox = true;
        public virtual bool HasBoundingBox
        {
            get
            {
                return hasBoundingBox;
            }
            set
            {
                hasBoundingBox = value;
            }
        }

        #endregion
    }
}
